<template>
  <el-dialog
    v-model="dialogVisible"
    title="导出代码"
    width="900px"
    class="export-dialog"
  >
    <div class="export-content">
      <div class="export-options">
        <el-radio-group v-model="exportType">
          <el-radio label="vue">Vue 3 组件</el-radio>
          <el-radio label="html">HTML 页面</el-radio>
          <el-radio label="json">JSON 数据</el-radio>
        </el-radio-group>
      </div>

      <div class="code-preview">
        <div class="preview-header">
          <span>{{ getCodeTitle() }}</span>
          <div class="header-actions">
            <el-button size="small" @click="copyCode">
              <el-icon><CopyDocument /></el-icon>
              复制代码
            </el-button>
            <el-button size="small" type="primary" @click="downloadCode">
              <el-icon><Download /></el-icon>
              下载文件
            </el-button>
          </div>
        </div>
        <div class="code-content">
          <pre><code>{{ generatedCode }}</code></pre>
        </div>
      </div>
    </div>

    <template #footer>
      <el-button @click="dialogVisible = false">关闭</el-button>
    </template>
  </el-dialog>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { CopyDocument, Download } from '@element-plus/icons-vue'

const props = defineProps({
  modelValue: { type: Boolean, default: false },
  components: { type: Array, default: () => [] },
  canvasConfig: { type: Object, default: () => ({}) }
})

const emit = defineEmits(['update:modelValue'])

const dialogVisible = ref(false)
const exportType = ref('vue')

watch(() => props.modelValue, (newVal) => {
  dialogVisible.value = newVal
})

watch(dialogVisible, (newVal) => {
  emit('update:modelValue', newVal)
})

const generatedCode = computed(() => {
  switch (exportType.value) {
    case 'vue':
      return generateVueCode()
    case 'html':
      return generateHtmlCode()
    case 'json':
      return generateJsonCode()
    default:
      return ''
  }
})

const getCodeTitle = () => {
  const titles = {
    vue: 'Vue 3 组件代码',
    html: 'HTML 页面代码',
    json: 'JSON 数据格式'
  }
  return titles[exportType.value] || '代码预览'
}

const generateVueCode = () => {
  const template = generateVueTemplate()
  const script = generateVueScript()
  const style = generateVueStyle()

  return `<template>
${template}
<` + `/template>

<script setup>
${script}
<` + `/script>

<style scoped>
${style}
<` + `/style>`
}

const generateVueTemplate = () => {
  let template = '  <div class="generated-page">'

  if (props.components.length === 0) {
    template += '\\n    <div class="empty-page">空页面</div>'
  } else {
    props.components.forEach(component => {
      template += '\\n' + generateComponentTemplate(component, '    ')
    })
  }

  template += '\\n  ' + '<' + '/div>'
  return template
}

const generateComponentTemplate = (component, indent) => {
  const style = generateInlineStyle(component)
  const styleAttr = style ? ` style="${style}"` : ''

  switch (component.type) {
    case 'text':
      return `${indent}<div class="text-component"${styleAttr}>${component.props.content}</div>`

    case 'button':
      return `${indent}<el-button type="${component.props.type}" size="${component.props.size}"${styleAttr}>${component.props.text}</el-button>`

    case 'image':
      return `${indent}<img src="${component.props.src}" alt="${component.props.alt}" class="image-component"${styleAttr} />`

    case 'input':
      return `${indent}<el-input placeholder="${component.props.placeholder}" type="${component.props.type}"${styleAttr}></el-input>`

    case 'textarea':
      return `${indent}<el-input type="textarea" placeholder="${component.props.placeholder}" rows="${component.props.rows}"${styleAttr}></el-input>`

    case 'select': {
      let selectTemplate = `${indent}<el-select placeholder="${component.props.placeholder}"${styleAttr}>`
      component.props.options?.forEach(option => {
        selectTemplate += `\\n${indent}  <el-option label="${option.label}" value="${option.value}"></el-option>`
      })
      selectTemplate += `\\n${indent}` + '<' + '/el-select>'
      return selectTemplate
    }

    case 'container':
      return `${indent}<div class="container-component"${styleAttr}></div>`

    case 'divider':
      return `${indent}<el-divider direction="${component.props.direction}"${styleAttr}></el-divider>`

    case 'line-chart':
    case 'bar-chart':
    case 'pie-chart': {
      const chartType = component.type.split('-')[0]
      return `${indent}<${chartType}-chart :data="chartData.${component.id}" title="${component.props.title}"${styleAttr}>` + '<' + `/${chartType}-chart>`
    }

    default:
      return `${indent}<div class="unknown-component"${styleAttr}>未知组件: ${component.type}</div>`
  }
}

const generateInlineStyle = (component) => {
  const styles = []

  // 位置样式
  styles.push(`position: absolute`)
  styles.push(`left: ${component.position.x}px`)
  styles.push(`top: ${component.position.y}px`)

  // 组件样式
  Object.entries(component.styles).forEach(([key, value]) => {
    if (value && key !== 'customStyle') {
      const cssKey = key.replace(/([A-Z])/g, '-$1').toLowerCase()
      styles.push(`${cssKey}: ${value}`)
    }
  })

  // 组件属性样式
  if (component.type === 'text') {
    if (component.props.fontSize) styles.push(`font-size: ${component.props.fontSize}`)
    if (component.props.color) styles.push(`color: ${component.props.color}`)
    if (component.props.fontWeight) styles.push(`font-weight: ${component.props.fontWeight}`)
    if (component.props.textAlign) styles.push(`text-align: ${component.props.textAlign}`)
  }

  if (component.type === 'image') {
    if (component.props.width) styles.push(`width: ${component.props.width}`)
    if (component.props.height) styles.push(`height: ${component.props.height}`)
  }

  // 自定义样式
  if (component.styles.customStyle) {
    // 将自定义样式按分号分割并添加到样式数组
    const customStyleParts = component.styles.customStyle.split(';')
    customStyleParts.forEach(part => {
      if (part.trim()) {
        styles.push(part.trim())
      }
    })
  }

  return styles.join('; ')
}

const generateVueScript = () => {
  let script = `import { ref } from 'vue'`

  // 检查是否有图表组件
  const hasCharts = props.components.some(c => c.type.includes('chart'))
  if (hasCharts) {
    script += `\\nimport LineChart from './charts/LineChart.vue'`
    script += `\\nimport BarChart from './charts/BarChart.vue'`
    script += `\\nimport PieChart from './charts/PieChart.vue'`
  }

  script += `\\n\\n// 响应式数据`

  // 图表数据
  if (hasCharts) {
    script += `\\nconst chartData = ref({`
    props.components.forEach(component => {
      if (component.type.includes('chart')) {
        script += `\\n  ${component.id}: ${JSON.stringify(component.props.data, null, 2).replace(/\\n/g, '\\n  ')},`
      }
    })
    script += `\\n})`
  }

  script += `\\n\\n// 这里可以添加更多逻辑`
  script += `\\nconsole.log('页面已加载')`

  return script
}

const generateVueStyle = () => {
  let style = `.generated-page {
  position: relative;
  width: 100%;
  min-height: 100vh;
  background: ${props.canvasConfig.backgroundColor || '#f5f5f5'};
  padding: ${props.canvasConfig.padding || '20px'};
}

.empty-page {
  text-align: center;
  color: #999;
  font-size: 18px;
  margin-top: 100px;
}

.text-component {
  display: inline-block;
  white-space: pre-wrap;
}

.image-component {
  display: block;
  max-width: 100%;
}

.container-component {
  border: 1px dashed #ccc;
  min-height: 60px;
}

.unknown-component {
  padding: 10px;
  border: 1px solid #ccc;
  background: #f5f5f5;
  color: #666;
}`

  return style
}

const generateHtmlCode = () => {
  const componentsHtml = generateHtmlComponents()

  return `<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>生成的页面</title>
  <link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css">
  <style>
    body {
      margin: 0;
      padding: 0;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    }
    .page-container {
      position: relative;
      width: 100%;
      min-height: 100vh;
      background: ${props.canvasConfig.backgroundColor || '#f5f5f5'};
      padding: ${props.canvasConfig.padding || '20px'};
    }
    .component {
      position: absolute;
    }
    .text-component {
      display: inline-block;
      white-space: pre-wrap;
    }
    .image-component {
      display: block;
      max-width: 100%;
    }
  </style>
</head>
<body>
  <div class="page-container">
${componentsHtml}
  </div>

  <script src="https://unpkg.com/vue@3/dist/vue.global.js">` + '<' + `/script>
  <script src="https://unpkg.com/element-plus/dist/index.full.js">` + '<' + `/script>
  <script>
    const { createApp } = Vue
    const app = createApp({
      data() {
        return {
          message: '页面已加载'
        }
      }
    })
    app.use(ElementPlus)
    app.mount('.page-container')
  ` + '<' + `/script>
</body>
</html>`
}

const generateHtmlComponents = () => {
  if (props.components.length === 0) {
    return '    <div style="text-align: center; color: #999; font-size: 18px; margin-top: 100px;">空页面</div>'
  }

  return props.components.map(component => {
    const style = generateInlineStyle(component)
    const styleAttr = style ? ` style="${style}"` : ''

    switch (component.type) {
      case 'text':
        return `    <div class="component text-component"${styleAttr}>${component.props.content}</div>`
      case 'button':
        return `    <button class="component"${styleAttr}>${component.props.text}</button>`
      case 'image':
        return `    <img class="component image-component" src="${component.props.src}" alt="${component.props.alt}"${styleAttr} />`
      case 'input':
        return `    <input class="component" placeholder="${component.props.placeholder}" type="${component.props.type}"${styleAttr} />`
      case 'textarea':
        return `    <textarea class="component" placeholder="${component.props.placeholder}" rows="${component.props.rows}"${styleAttr}></textarea>`
      default:
        return `    <div class="component"${styleAttr}>组件: ${component.type}</div>`
    }
  }).join('\\n')
}

const generateJsonCode = () => {
  const exportData = {
    pageInfo: {
      title: '导出页面',
      description: '通过低代码平台生成的页面',
      exportTime: new Date().toISOString(),
      version: '1.0.0'
    },
    canvasConfig: props.canvasConfig,
    components: props.components.map(component => ({
      id: component.id,
      type: component.type,
      position: component.position,
      props: component.props,
      styles: component.styles
    }))
  }

  return JSON.stringify(exportData, null, 2)
}

const copyCode = async () => {
  try {
    await navigator.clipboard.writeText(generatedCode.value)
    ElMessage.success('代码已复制到剪贴板')
  } catch (error) {
    ElMessage.error('复制失败，请手动复制')
    console.error('复制失败:', error)
  }
}

const downloadCode = () => {
  const fileExtensions = {
    vue: '.vue',
    html: '.html',
    json: '.json'
  }

  const fileName = `generated-page${fileExtensions[exportType.value]}`
  const blob = new Blob([generatedCode.value], {
    type: exportType.value === 'json' ? 'application/json' : 'text/plain'
  })
  const url = URL.createObjectURL(blob)

  const a = document.createElement('a')
  a.href = url
  a.download = fileName
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  URL.revokeObjectURL(url)

  ElMessage.success(`文件 ${fileName} 已下载`)
}
</script>

<style lang="scss" scoped>
.export-dialog {
  :deep(.el-dialog__body) {
    padding: 0;
  }
}

.export-content {
  display: flex;
  flex-direction: column;
  height: 70vh;
}

.export-options {
  padding: 20px;
  border-bottom: 1px solid #e4e7ed;
  background: #f8f9fa;
}

.code-preview {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.preview-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 20px;
  background: #fafafa;
  border-bottom: 1px solid #e4e7ed;
  font-weight: 500;
  color: #303133;

  .header-actions {
    display: flex;
    gap: 8px;
  }
}

.code-content {
  flex: 1;
  overflow: auto;
  background: #f8f8f8;

  pre {
    margin: 0;
    padding: 20px;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 13px;
    line-height: 1.5;
    white-space: pre-wrap;
    word-wrap: break-word;
    color: #2c3e50;

    code {
      background: none;
      padding: 0;
      font-size: inherit;
      color: inherit;
    }
  }
}

:deep(.el-radio-group) {
  .el-radio {
    margin-right: 20px;
  }
}
</style>
